home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / fp / ifp_unix.lzh / ifp / interp / file.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-23  |  13.3 KB  |  538 lines

  1.  
  2. /****** file.c ********************************************************/
  3. /**                                                                  **/
  4. /**                    University of Illinois                        **/
  5. /**                                                                  **/
  6. /**                Department of Computer Science                    **/
  7. /**                                                                  **/
  8. /**   Tool: IFP                         Version: 0.5                 **/
  9. /**                                                                  **/
  10. /**   Author:  Arch D. Robison          Date:   May 1, 1985          **/
  11. /**                                                                  **/
  12. /**   Revised by: Arch D. Robison       Date: June 22, 1986          **/
  13. /**                                                                  **/
  14. /**   Principal Investigators: Prof. R. H. Campbell                  **/
  15. /**                            Prof. W. J. Kubitz                    **/
  16. /**                                                                  **/
  17. /**                                                                  **/
  18. /**------------------------------------------------------------------**/
  19. /**   (C) Copyright 1987  University of Illinois Board of Trustees   **/
  20. /**                       All Rights Reserved.                       **/
  21. /**********************************************************************/
  22.  
  23.  
  24. #include <stdio.h>
  25. #include "struct.h"
  26. #include "string.h"
  27. #include "node.h"
  28. #include "umax.h"
  29. #include "inob.h"
  30.  
  31. extern char *strcpy (),*strcat (),*getenv ();
  32.  
  33. /*------------------------- Operating System Constants --------------------*
  34.  *
  35.  * Operating System Constants
  36.  *
  37.  * PATH_SEPARATOR = separator used for file names
  38.  * EDITOR = path to editor
  39.  * EdCommand = IFP command to invoke EDITOR
  40.  *
  41.  * Even operating systems without hierarchical file systems must
  42.  * define a PATH_SEPARATOR, which is used still used internally.
  43.  *
  44.  * In the case of CTSS, we also have a constant USER_PATH.  This
  45.  * a fictious path to the user's current directory. 
  46.  */ 
  47.  
  48. #if OPSYS==UNIX
  49. #define PATH_SEPARATOR '/'
  50. #define EDITOR "/bin/vi"
  51. char *EdCommand;
  52. #endif
  53.  
  54. #if OPSYS==MSDOS
  55. #define PATH_SEPARATOR '\\'
  56. #define EDITOR "c:ed.exe"
  57. char *EdCommand = "ed";
  58. char DirPath [MAXPATH+1] = "c:dir.exe";
  59. #endif
  60.  
  61. #if OPSYS==CTSS
  62. #define PATH_SEPARATOR '/'
  63. #define EDITOR "fred"
  64. char *EdCommand = "fred";
  65. #define USER_PATH "/usr"
  66. #endif
  67.  
  68. #if OPSYS==APPLE
  69. #define PATH_SEPARATOR ':'
  70. #define EDITOR "apple_editor"
  71. char * EdCommand = EDITOR;
  72. #endif
  73.  
  74. /*-------------------- end of Operating System Constants --------------------*/
  75.  
  76. char RootPath [MAXPATH+1] = "";         /* Path to IFP's root */
  77.  
  78. char EditorPath [MAXPATH+1] = EDITOR;   /* value is default */
  79.  
  80. char FPprompt[16] = "ifp> ";   /* value is default */
  81. NodePtr CurWorkDir = NULL;     /* Current working directory node */
  82.  
  83. /********************** Operating system file interface ***********************/
  84.  
  85. /*
  86.  * PathTail
  87.  *
  88.  * Return the last component in a path name.
  89.  * Returns pointer to "" if error occurs.
  90.  */
  91. private char *PathTail (Path)
  92.    char *Path;
  93.    {
  94.       register char *T;
  95.  
  96.       if (*Path == PATH_SEPARATOR) Path++;
  97.       while (*Path) {
  98.      for (T = Path; *T++ != PATH_SEPARATOR; )
  99.         if (!*T) return Path;
  100.      Path = T;
  101.       }
  102.       return Path;
  103.    }
  104.  
  105. /*------------------------------ fopen hacks ------------------------------
  106.  *
  107.  * Both MSDOS and CTSS have problems with hierarchical file structure.
  108.  * Thus we have to redefine the standard UNIX function "fopen" to allow
  109.  * for these operating system's quirks.
  110.  */
  111. #if OPSYS==MSDOS
  112.  
  113. /*
  114.  * We try to keep track of the current directory in CWDCache so we can avoid
  115.  * superfluous calls to chdir.  Set the 0th character to '\0' to empty the
  116.  * cache.
  117.  */
  118. char CWDCache [MAXPATH] = "";
  119.  
  120. /*
  121.  * PathSplit
  122.  *
  123.  * Split a pathname into its directory and file parts.
  124.  * Change directory to directory part.
  125.  *
  126.  * Input
  127.  *      PathName = pathname
  128.  *
  129.  * Output
  130.  *      NULL if error occurs, pointer to file name otherwise.
  131.  */
  132. char *PathSplit (PathName)      /* also used by command.c */
  133.    char *PathName;
  134.    {
  135.       register char *S,*T;
  136.       register int R;
  137.  
  138.       T = PathTail (PathName);
  139.       if (T != &PathName [1]) {
  140.      T[-1] = '\0';
  141.      S = PathName;          /* Break string at path separator */
  142.       } else S = "\\";
  143.       if (strcmp (S,CWDCache)) {
  144.      R = chdir (S);
  145.      if (Debug & DebugFile) printf ("cache load: %d = ChDir (%s) for %s\n",R,S,T);
  146.      (void) strcpy (CWDCache,S);
  147.       } else {
  148.      if (Debug & DebugFile) printf ("cache HIT!\n"); 
  149.      R = 0;
  150.       }
  151.       T[-1] = PATH_SEPARATOR;   /* Replace path separator */
  152.       return R ? NULL : T;
  153.    }
  154.  
  155. /*
  156.  * DOSfopen
  157.  *
  158.  * Works as =`fopen' should.  The old Lattice C `fopen' would not take 
  159.  * pathnames.  Even though the new compiler's will allow long names,
  160.  * the fake fopen can take advantage of the current directory cache.
  161.  */
  162. private FILE *DOSfopen (FileName,Mode)
  163.    char *FileName,*Mode;
  164.    {
  165.       char *T;
  166.  
  167.       return (T = PathSplit (FileName)) != NULL ? fopen (T,Mode) : NULL;
  168.    }
  169.  
  170. #define fopen DOSfopen
  171.  
  172. #endif /* OPSYS==MSDOS */
  173.  
  174. #if OPSYS==CTSS
  175. /*
  176.  * CTSSfopen
  177.  *
  178.  * Tries for fake a real fopen.  CTSS does not support hierarchical file
  179.  * structures, so CTSSfopen takes the tail of the path as the file name.
  180.  */
  181. private FILE *CTSSfopen (FileName,Mode)
  182.    char *FileName,*Mode;
  183.    {
  184.       register char *T;
  185.  
  186.       if (Debug & DebugFile) printf ("CTSSfopen (%s,%s)\n",FileName,Mode);
  187.       T = PathTail (FileName);
  188.       if (T == &FileName[1]) return NULL;
  189.       else {
  190.      T[-1] = '\0';
  191.      if (strcmp (FileName,USER_PATH)) return NULL;
  192.      else {
  193.         if (Debug & DebugFile) printf ("fopen (%s,%s)\n",T,Mode);
  194.         return fopen (T,Mode);
  195.      }
  196.       }
  197.    }
  198. #define fopen CTSSfopen
  199.  
  200. #endif /* OPSYS==CTSS */
  201.  
  202. /*---------------------------- end of fopen hacks ----------------------------*/
  203.  
  204. /*
  205.  * FormNPath
  206.  *
  207.  * Create the pathname for a given node.
  208.  *
  209.  * Input
  210.  *      N = pointer to node
  211.  *      PathLim = pointer to end of PathName buffer
  212.  *
  213.  * Output
  214.  *      Pathname for node
  215.  */
  216. char *FormNPath (N,PathName,PathLim)
  217.    register NodePtr N;
  218.    char PathName[];
  219.    register char *PathLim;
  220.    {
  221.       CharPtr U;
  222.       register char *T;
  223.       if (N->NodeParent == NULL) {
  224.      (void) strcpy (PathName,RootPath);
  225.      return &PathName [strlen (PathName)];
  226.       } else {
  227.      T = FormNPath (N->NodeParent,PathName,PathLim);
  228.      if (T==NULL) return NULL;
  229.      else {
  230.         *T++ = PATH_SEPARATOR;
  231.         CPInit (&U,&N->NodeName);
  232.         (void) CPRead (&U,T,PathLim-T);
  233. #if OPSYS==UNIX||OPSYS==APPLE
  234.         T += strlen (T);
  235. #endif
  236. #if OPSYS==MSDOS || OPSYS==CTSS 
  237.         /* DOS and CTSS names limited to 8 characters */
  238.         {
  239.            int L;               
  240.            if ((L = strlen (T)) > 8) L = 8;
  241.            *(T += L) = '\0';
  242.         }
  243. #endif
  244.         if (!CPRead (&U,T,PathLim-T)) return T;
  245.         else return NULL; /* U should be empty */
  246.      }
  247.       }
  248.    }
  249.  
  250.  
  251. /*
  252.  * FormPath
  253.  *
  254.  * Make UNIX or DOS pathname for node
  255.  *
  256.  * Input
  257.  *      N = node or path list
  258.  *      PathName = buffer to put pathname in.
  259.  *      PathLim = pointer to end of buffer
  260.  *
  261.  * Output
  262.  *      PathName = pathname if successful
  263.  */
  264. void FormPath (N,PathName,PathLim)
  265.    register ObjectPtr N;
  266.    char PathName[];
  267.    char *PathLim;
  268.    {
  269.       register char *T;
  270.       CharPtr U;
  271.       register ListPtr P;
  272.       register int K;
  273.  
  274.       switch (N->Tag) {
  275.  
  276.      case LIST:
  277.         (void) strcpy (PathName,RootPath);
  278.         K = strlen (PathName);
  279.         PathLim -= K;
  280.         T = &PathName [K];
  281.         for (P = N->List; P!=NULL; P=P->Next) {
  282.            if (P->Val.Tag != STRING) return;
  283.            else {
  284.           CPInit (&U,&P->Val.String);
  285.           (void) CPRead (&U,T,PathLim-PathName);
  286. #if OPSYS==UNIX||OPSYS==APPLE
  287.           T += strlen (T);
  288. #endif
  289. #if OPSYS==MSDOS || OPSYS==CTSS 
  290.           /* DOS names are limited to 8 characters */
  291.           if ((K = strlen (T)) > 8) K = 8; 
  292.           *(T += K) = '\0';
  293. #endif
  294.           /* T should always be <= PathLim */
  295.           if (T >= PathLim) return;
  296.            }
  297.         }
  298.         break;
  299.  
  300.      case NODE:
  301.         (void) FormNPath (N->Node,PathName,PathLim);
  302.         break;
  303.  
  304.      default:
  305.         break;
  306.       }
  307.    }
  308.  
  309. /*
  310.  * ReadDef (IFP)
  311.  *
  312.  * Read a definition node.  The definition node tag must be BOTTOM upon 
  313.  * entry when running UMAX.
  314.  *
  315.  * Input
  316.  *      Caller = pointer to DEF node of caller
  317.  *      Fun = object with tag NODE. 
  318.  *
  319.  * -------------------------------------------
  320.  *
  321.  * ReadClass (OOFP)
  322.  *
  323.  * Read an object file.
  324.  *
  325.  * Input
  326.  *    ClassName = name of class
  327.  */
  328. void ReadDef (Caller,Fun)
  329.    NodePtr Caller;
  330.    ObjectPtr Fun;
  331.    {
  332.       FILE *DefFile;
  333.       InDesc F;
  334.       int C;
  335.       NodePtr N;
  336.       char FileName[MAXPATH];
  337.  
  338.       if (NULL == FormNPath (N=Fun->Node,FileName,&FileName[MAXPATH])) 
  339.      DefError (Caller,Fun,"invalid name for function");
  340.       else
  341.      while (NULL != (DefFile = fopen (FileName,"r"))) {
  342.         InitIn (&F,N->NodeParent,DefFile,0);
  343.         C = InDef (&F,N->NodeName,&N->NodeData.NodeDef.DefCode);
  344.         (void) fclose (F.InFile);
  345.         if (C) goto exit;
  346.         printf ("Do you wish to edit %s ? ",FileName + strlen (RootPath));
  347.         while (1) {
  348.            for (C = getchar (); getchar ()!='\n';) continue;
  349.            if (C == 'y') {
  350.           ExecEdit (FileName); 
  351.           break;
  352.            }
  353.            if (C == 'n') goto exit;
  354.            printf ("Respond with y or n\n");
  355.         }
  356.      } 
  357. exit:;
  358.    }
  359.  
  360. /*
  361.  * ReadImport
  362.  *
  363.  * Read the import file for a module node.
  364.  *
  365.  * Input
  366.  *      M = pointer to module node
  367.  */
  368. void ReadImport (M)
  369.    NodePtr M;
  370.    {
  371.       char *T;
  372.       char FileName[MAXPATH];
  373.       FILE *ImpFile;
  374.       InDesc F;
  375.  
  376.       if (NULL != (T = FormNPath (M,FileName,&FileName[MAXPATH]))) {
  377.      *T++ = PATH_SEPARATOR;
  378.      (void) strcpy (T,"%IMPORT");
  379.      if (NULL != (ImpFile = fopen (FileName,"r"))) {
  380.         InitIn (&F,M,ImpFile,0);
  381.         InImport (&F,M);
  382.         (void) fclose (ImpFile);
  383.      }
  384.       }
  385.    }
  386.  
  387. #if OPSYS!=CTSS
  388. /*
  389.  * EnvGet
  390.  *
  391.  * Get value for environment variable.
  392.  *
  393.  * Input
  394.  *      Key = enviroment variable name
  395.  *      Value = default value for variable
  396.  *      ValLim = length of Value buffer
  397.  *
  398.  * Output
  399.  *      Value = value of enviroment variable, or default if not found.
  400.  */
  401. void EnvGet (Key,Value,ValLim)
  402.    char *Key,*Value;
  403.    int ValLim;
  404.    {
  405.       char *V;
  406.  
  407.       V = getenv (Key);
  408.       if (V != NULL)
  409.      if (strlen (V) < ValLim) (void) strcpy (Value,V);
  410.      else fprintf (stderr,"Error: %s in enviroment is longer than %d\n",
  411.                Key,MAXPATH-3);
  412.    }
  413.  
  414. /*
  415.  * CWDGet
  416.  *
  417.  * Find pathname of current working directory (relative to FP root).
  418.  *
  419.  * Input
  420.  *      PathLim = length of Path buffer (used by PCAT versions only)
  421.  *
  422.  * Output
  423.  *      result = 1 if valid FP path, 0 otherwise
  424.  *      Path = FP pathname if valid, undefined otherwise
  425.  */
  426. boolean CWDGet (Path,PathLim)
  427.    register char *Path;
  428.    int PathLim;
  429.    {
  430. #ifdef PCAT
  431.       extern char *getcwd ();
  432.       if (!getcwd (Path,PathLim-2)) return 0;
  433. #else
  434. #if S9000
  435.       extern FILE *popen ();
  436.       FILE *F;                          /* S9000 Xenix has no getwd! */
  437.       F = popen ("/bin/pwd","r");
  438.       fscanf (F,"%s",Path);
  439.       pclose (F);
  440. #else
  441.       extern char *getwd();
  442.       if (!getwd (Path)) return 0;
  443. #endif /* S9000 */
  444. #endif /* PCAT */
  445.  
  446. #if OPSYS==MSDOS
  447.       (void) strcpy (Path,Path+2);              /* Delete drive name */
  448.       if (Debug & DebugFile) printf ("CWD = '%s'\n",Path); 
  449.       return 1;
  450. #endif
  451. #if OPSYS==UNIX
  452.       {
  453.      register int K;
  454.      K = strlen (RootPath);
  455.      if (strncmp (Path,RootPath,K)) return 0;
  456.      else {
  457.         (void) strcpy (Path,&Path[K]);    /* Remove FP root path prefix */
  458.         return 1;
  459.      }
  460.       }
  461. #endif /* OPSYS==UNIX */
  462.    }
  463. #endif /* OPSYS != CTSS */
  464.  
  465. /*
  466.  * InitFile
  467.  *
  468.  * The DOS version is kludgy.  The problem is that DOSfopen changes
  469.  * the current directory, thus munging it before CWDGet is called.
  470.  */
  471. #if OPSYS==UNIX || OPSYS==CTSS || OPSYS==APPLE
  472. void InitFile ()
  473. #endif
  474. #if OPSYS==MSDOS
  475. void InitFile (CWD)
  476.    char *CWD;
  477. #endif
  478.    {
  479.       InDesc F;
  480.       if (Debug & DebugFile) printf ("enter InitFile\n");
  481. #if OPSYS!=CTSS
  482.       EnvGet ("EDITOR",EditorPath,MAXPATH);
  483. #endif
  484.       if (Debug & DebugFile) printf ("EditorPath = `%s'\n",EditorPath);
  485. #if OPSYS==UNIX
  486.       EdCommand = PathTail (EditorPath);
  487.       if (!*EdCommand) {
  488.      fprintf (stderr,"\n * EDITOR environment variable not a full path.");
  489.      fprintf (stderr,"\n   Setting editor to '%s'.\n",EDITOR);
  490.      EdCommand = PathTail (strcpy (EditorPath,EDITOR));
  491.       }
  492.       EnvGet ("IFPprompt",FPprompt,sizeof (FPprompt));
  493. #endif
  494. #if OPSYS==MSDOS
  495.       EnvGet ("IFPDIR",DirPath,MAXPATH);
  496.       if (Debug & DebugFile) printf ("IFPDIR = '%s'\n",DirPath);
  497. #endif
  498.  
  499.       /* Create dummy descriptor for reading current directory */
  500.       InitIn (&F,(NodePtr) NULL,(FILE *) NULL, -1); 
  501.  
  502. #if OPSYS==UNIX
  503.       if (!CWDGet (F.InBuf,INBUFSIZE-1)) {
  504.      fprintf (stderr,"\n\n * Current directory not an IFP subdirectory.");
  505.      fprintf (stderr,  "\n * Setting current directory to IFP root (%s).\n",
  506.                   RootPath);
  507.      if (chdir (RootPath)) {
  508.         extern int errno;
  509.         perror (RootPath);
  510.         exit (errno);
  511.      } else F.InBuf[0] = '\0';
  512.       }
  513. #endif
  514. #if OPSYS==MSDOS
  515.       {
  516.      register char *T;
  517.      (void) strcpy (F.InBuf,CWD);
  518.      for (T=F.InBuf; *T; T++)
  519.         if (*T == PATH_SEPARATOR) *T = '/';
  520.       }
  521. #endif
  522. #if OPSYS==CTSS
  523.       (void) strcpy (F.InBuf,USER_PATH);
  524. #endif
  525.       if (F.InBuf[0]) {
  526.          Object X;
  527.      (void) strcat (F.InPtr,"\n");
  528.      (void) InNode (&F,&X,NIL);
  529.      CurWorkDir = MakeNode (X.List,MODULE);
  530.       } else 
  531.      CurWorkDir = RootNode;
  532.       if (Debug & DebugFile) printf ("exit InitFile\n");
  533.    }
  534.  
  535.  
  536. /************************* end of file.c *******************************/
  537.  
  538.